package com.example.demo.utils;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * *********************************************************************
 * JsonUtils.java
 * <p>
 * H3C所有，
 * 受到法律的保护，任何公司或个人，未经授权不得擅自拷贝。
 *
 * @copyright Copyright: 2015-2020
 * @creator xfw2218<br />
 * @create-time 2018年2月26日 下午8:06:26
 * @revision $Id:  *
 * *********************************************************************
 */
public class JsonUtils {
    /**
     * 日志记录
     */
    private static final Logger log = LoggerFactory.getLogger(JsonUtils.class);
    private final static ObjectMapper OBJECT_MAPPER;

    static {
        OBJECT_MAPPER = new ObjectMapper();
        OBJECT_MAPPER.setSerializationInclusion(Include.NON_NULL);
        OBJECT_MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    }

    /**
     *
     */
    static boolean isPretty = true;

    public static ObjectMapper getObjectmapper() {
        return OBJECT_MAPPER;
    }


    /**
     * json串转化成实体
     *
     * @param is
     * @param tr
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T json2GenericObject(InputStream is, TypeReference<T> tr) {
        if (is == null) {
            return null;
        } else {
            try {
                return (T) OBJECT_MAPPER.readValue(is, tr);
            } catch (Throwable t) {
                log.error("json error:", t);
            } finally {
                if (is != null) {
                    try {
                        is.close();
                    } catch (IOException e) {
                        if (log.isDebugEnabled()) {
                            log.debug("json error:", e);
                        }
                    }
                }
            }
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public static <T> T json2GenericObject(String jsonString, TypeReference<T> tr) {
        if (jsonString == null || "".equals(jsonString.trim())) {
            return null;
        } else {
            try {
                return (T) OBJECT_MAPPER.readValue(jsonString, tr);
            } catch (Throwable t) {
                log.error("json error:", t);
            }
        }
        return null;
    }

    /**
     * 当为空值不显示双引号
     *
     * @param object
     * @return
     */
    public static String toJsonOfEmpty(Object object) {
        String jsonString = toJson(object, isPretty);
        jsonString = jsonString.replace("\"\"", "null");
        return jsonString;
    }

    /**
     * 对象转化层json字符串
     *
     * @param object
     * @return
     */
    public static String toJson(Object object) {
        return toJson(object, isPretty);
    }

    public static String toJson(Object object, boolean isPretty) {
        String jsonString = "";
        try {
            if (isPretty) {
                jsonString = OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(object);
            } else {
                jsonString = OBJECT_MAPPER.writeValueAsString(object);
            }
        } catch (JsonProcessingException e) {
            log.error("toJson error " + e.getMessage(), e);
        }
        return jsonString;
    }

    /**
     * json字符串转化成对象
     *
     * @param jsonString
     * @param c
     * @return
     */
    public static <T> T json2Object(String jsonString, Class<T> c) {
        if (jsonString == null || "".equals(jsonString.trim())) {
            return null;
        } else {
            try {
                return c.cast(OBJECT_MAPPER.readValue(jsonString, c));
            } catch (Throwable t) {
                log.error("json error:", t);
            }
        }
        return null;
    }


    public static <T> T json2Object(InputStream is, Class<T> c) {
        if (is == null) {
            return null;
        } else {
            try {
                return c.cast(OBJECT_MAPPER.readValue(is, c));
            } catch (Throwable t) {
                log.error("json error:", t);
            } finally {
                if (is != null) {
                    try {
                        is.close();
                    } catch (IOException e) {
                        if (log.isDebugEnabled()) {
                            log.debug("json error:", e);
                        }
                    }
                }
            }
        }
        return null;
    }

    /**
     * @param json
     * @param tagPath
     * @return
     * @throws Exception
     */
    public static List<String> readValues(String json, String tagPath) throws Exception {
        List<String> value = new ArrayList<String>();
        if (isEmpty(json) || (isEmpty(tagPath))) {
            return value;
        }
        ObjectMapper mapper = new ObjectMapper();
        String[] path = tagPath.split(":");
        JsonNode node = mapper.readTree(json);
        getJsonValue(node, path, value, 1);

        return value;
    }

    public static String readValueFromJson(String json, String tagPath) throws Exception {
        List<String> value = new ArrayList<String>();
        if (isEmpty(json) || (isEmpty(tagPath))) {
            return "";
        }
        ObjectMapper mapper = new ObjectMapper();
        String[] path = tagPath.split(":");
        JsonNode node = mapper.readTree(json);
        getJsonValue(node, path, value, 1);
        return value.get(0).replaceAll("\"", "");
    }

    private static void getJsonValue(JsonNode node, String[] path, List<String> values, int nextIndex) {
        if (isEmpty(node)) {
            return;
        }
        if (nextIndex == path.length) {
            if (node.isArray()) {
                for (int i = 0; i < node.size(); i++) {
                    JsonNode child = node.get(i).get(path[nextIndex - 1]);
                    if (isEmpty(child)) {
                        continue;
                    }
                    values.add(child.toString());
                }
            } else {
                JsonNode child = node.get(path[nextIndex - 1]);
                if (!isEmpty(child)) {
                    values.add(child.toString());
                }
            }
            return;
        }
        node = node.get(path[nextIndex - 1]);
        if (node.isArray()) {
            for (int i = 0; i < node.size(); i++) {
                getJsonValue(node.get(i), path, values, nextIndex + 1);
            }
        } else {
            getJsonValue(node, path, values, nextIndex + 1);
        }
    }

    private static boolean isEmpty(Object obj) {
        boolean result = true;
        if (obj == null) {
            return true;
        }
        if (obj instanceof String) {
            result = (obj.toString().trim().length() == 0) || "null".equals(obj.toString().trim());
        } else if (obj instanceof Collection) {
            result = ((Collection<?>) obj).size() == 0;
        } else {
            result = ((obj == null) || (obj.toString().trim().length() < 1)) ? true : false;
        }
        return result;
    }

}
